"""
RSR(Rank-Sum Ratio, 秩和比综合评价法)
"""

'''什么是综合评价
使用比较系统的、规范的方法对于多个指标、多个单位同时进行评价的方法，也叫多指标综合评价方法。

综合评价的方法一般是主客观结合的，方法的选择需基于实际指标数据情况选定，最为关键的是指标的选取，以及指标权重的设置，这些需要基于广泛的调研和扎实的业务知识，不能说单纯的从数学上解决的。

综合评价的应用领域和范围非常广泛。从学科领域上看，在自然科学中广泛应用于各种事物的特征和性质的评价。比如，环境监测综合评价、药物临床试验综合评价、地质灾害综合评价、气候特征综合评价、产品质量综合评价等等；在社会科学中广泛应用于总体特征和个体特征的综合评价。比如，社会治安综合评价，生活质量综合评价、社会发展综合评价、教学水平综合评价、人居环境综合评价等等。在经济学学科领域更为普遍。如，综合经济效益评价、小康建设进程评价、经济预警评价分析、生产方式综合评价、房地产市场景气程度综合评价等等。
'''

'''综合评价方法的特点
综合评价可以避免一般评价方法局限性，使得运用多个指标对多个单位进行的评价成为可能。这种方法从计算及其需要考虑的问题上看都比较复杂，但由于其显著的特点：综合性和系统性，使得综合评价方法得到人们的认可。并在实践中广泛应用，如工业经济效益综合评价，小康生活水平综合评价、科技进步的综合评价，国家（地区）的综合实力评价、和谐社会评价等。随着计算机的普及，综合评价的计算方法的复杂性已经不成问题，其综合性和系统性表现得更加突出，使得综合评价方法作用突出。

评价过程也是一种决策过程。一般地说评价是指按照一定的标准（客观/主观、明确/模糊、定性/定量），对特定事物、行为、认识、态度等等评价客体的价值或优劣好坏进行评判比较的一种认知过程，同时也是一种决策过程。
'''

'''RSR秩和比综合评价法
RSR法(Rank-sum ratio) 是我国田凤调教授于1988年提出的，集古典参数统计与近代非参数统计各自优点于一体的统计分析方法。RSR法现在广泛地应用于医疗卫生、科技、经济等邻域的多指标综合评价、统计预测预报、鉴别分类、统计质量控制等方面。

一般过程是将效益型指标从小到大排序进行排名、成本型指标从大到小排序进行排名，再计算秩和比，最后统计回归、分档排序。通过秩转换，获得无量纲统计量RSR；在此基础上，运用参数统计分析的概念与方法，研究RSR的分布；以RSR值对评价对象的优劣直接排序或分档排序，从而对评价对象做出综合评价。

优点：以非参数法为基础，对指标的选择无特殊要求，适用于各种评价对象，由于计算时使用的数值是秩次，可以消除异常值的干扰

缺点：排序的主要依据是利用原始数据的秩次，最终算得的 RSR 值反映的是综合秩次的差距，而与原始数据的顺位间的差距程度大小无关，这样在指标转化为秩次是会失去一些原始数据的信息，如原始数据的大小差别等。当 RSR 值实际上不满足正态分布时，分档归类的结果与实际情况会有偏差，且只能回答分级程度是否有差别，不能进一步回答具体的差别情况。
'''

'''RSR 法本质
RSR 只使用了数据的相对大小关系，而不真正运用数值本身，也能用于处理“好”、“较好”、“一般”这类模糊指标问题。只要选择恰当的权重，RSR 法也能转化为模糊综合评价。

实际上，只要确定了权重，编好了秩，原始样本的排序就结束了，但是 RSR 综合评价法再进行了统计回归、分档排序，这一步实际上是通过将样本的秩次分布映射到正态分布曲线上，运用正态分布 3 sigma 原则进行分档。
'''




import pandas as pd
import numpy as np
import statsmodels.api as sm
from scipy.stats import norm
class RSR:
    """RSR 综合评价法

        Step 1: 列出原始数据表并编秩

        Step 2: 计算秩和比并排序

        Step 3: 确定RSR的分布(转化为概率单位)

        Step 4: 计算直线回归方程

        Step 5: 通过检验回归方程输出 RSR 矫正值，并进行分档排序
    """
    def __init__(self):
        pass

    def run(self, data, weight=None, threshold=None, full_rank=True):
        result = pd.DataFrame()
        n, m = data.shape

        # 对原始数据编秩
        if full_rank:
            for i, X in enumerate(data.columns):
                result[f'X{str(i + 1)}：{X}'] = data.iloc[:, i]
                result[f'R{str(i + 1)}：{X}'] = data.iloc[:,
                                                         i].rank(method="dense")
        else:
            for i, X in enumerate(data.columns):
                result[f'X{str(i + 1)}：{X}'] = data.iloc[:, i]
                result[f'R{str(i + 1)}：{X}'] = 1 + (n - 1) * (data.iloc[:, i].max() -
                                                              data.iloc[:, i]) / (data.iloc[:, i].max() - data.iloc[:, i].min())

        # 计算秩和比
        weight = 1 / m if weight is None else np.array(weight) / sum(weight)
        result['RSR'] = (result.iloc[:, 1::2] * weight).sum(axis=1) / n
        result['RSR_Rank'] = result['RSR'].rank(ascending=False)

        # 绘制 RSR 分布表
        RSR = result['RSR']
        RSR_RANK_DICT = dict(zip(RSR.values, RSR.rank().values))
        distribution = pd.DataFrame(index=sorted(RSR.unique()))
        distribution['f'] = RSR.value_counts().sort_index()
        distribution['Σ f'] = distribution['f'].cumsum()
        distribution[r'\bar{R} f'] = [RSR_RANK_DICT[i]
                                      for i in distribution.index]
        distribution[r'\bar{R}/n*100%'] = distribution[r'\bar{R} f'] / n
        distribution.iat[-1, -1] = 1 - 1 / (4 * n)
        distribution['Probit'] = 5 - norm.isf(distribution.iloc[:, -1])

        # 计算回归方差并进行回归分析
        r0 = np.polyfit(distribution['Probit'], distribution.index, deg=1)
        print(sm.OLS(distribution.index, sm.add_constant(
            distribution['Probit'])).fit().summary())
        if r0[1] > 0:
            print(f"\n回归直线方程为：y = {r0[0]} Probit + {r0[1]}")
        else:
            print(f"\n回归直线方程为：y = {r0[0]} Probit - {abs(r0[1])}")

        # 代入回归方程并分档排序
        result['Probit'] = result['RSR'].apply(
            lambda item: distribution.at[item, 'Probit'])
        result['RSR Regression'] = np.polyval(r0, result['Probit'])
        threshold = np.polyval(
            r0, [2, 4, 6, 8]) if threshold is None else np.polyval(r0, threshold)
        result['Level'] = pd.cut(
            result['RSR Regression'], threshold, labels=range(len(threshold) - 1, 0, -1))

        return result, distribution


    def save_res(self, data, file_name=None, **kwargs):
        result, distribution = self.run(data, **kwargs)
        file_name = 'RSR 分析结果报告.xlsx' if file_name is None else file_name + '.xlsx'
        writer = pd.ExcelWriter(file_name)
        result.to_excel(writer, '综合评价结果')
        result.sort_values(by='Level', ascending=False).to_excel(
            writer, '分档排序结果')
        distribution.to_excel(writer, 'RSR分布表')
        writer.save()
        writer.close()
        return result, distribution


data = pd.read_csv('data/river.csv', delimiter=',').drop(['河流'], axis=1)
rsr = RSR()
rsr.save_res(data, '第14章：综合评价与决策方法/RSR_res')